﻿#include "base/xrtc_engine.h"

#include <api/media_stream_interface.h>
#include <rtc_base/task_utils/to_queued_task.h>
#include <modules/video_capture/video_capture_factory.h>

#include "media_source/vcm_capturer.h"
#include "base/xrtc_global.h"
#include "base/xrtc_preview.h"
#include "base/xrtc_pusher.h"
#include "base/xrtc_player.h"

namespace xrtc {

IXRTCEngine* CreateXRTCEngine(XRTCEngineObserver* observer) {
    return XRTCGlobal::Instance()->api_thread()->Invoke<IXRTCEngine*>(
        RTC_FROM_HERE, [=]() {
            XRTCGlobal::Instance()->RegisterXRTCEngineObserver(observer);
            return new XRTCEngine();
        });
}

void DestroyXRTCEngine(IXRTCEngine* engine) {
    XRTCGlobal::Instance()->api_thread()->PostTask(webrtc::ToQueuedTask([=]() {
        if (engine) {
            delete engine;
        }
    }));
}

XRTCEngine::XRTCEngine() :
    video_device_(webrtc::VideoCaptureFactory::CreateDeviceInfo()),
    audio_device_(webrtc::AudioDeviceModule::Create(
        webrtc::AudioDeviceModule::kPlatformDefaultAudio,
        XRTCGlobal::Instance()->task_queue_factory())
    )
{
    if (audio_device_) {
        audio_device_->Init();
    }
}

XRTCEngine::~XRTCEngine() {
}

std::vector<XRTCDeviceInfo> XRTCEngine::GetVideoDeviceList() {
    return XRTCGlobal::Instance()->api_thread()
        ->Invoke<std::vector<XRTCDeviceInfo>>(RTC_FROM_HERE, [=]() {
            std::vector<XRTCDeviceInfo> device_list;

            uint32_t total = video_device_->NumberOfDevices();
            if (0 == total) {
                return device_list;
            }

            char id[128];
            char name[128];
            for (size_t index = 0; index < total; ++index) {
                id[0] = '\0';
                name[0] = '\0';
                
                int32_t res = video_device_->GetDeviceName(
                    index, name, sizeof(name), id, sizeof(id));
                if (res != 0) {
                    continue;
                }

                XRTCDeviceInfo device;
                device.device_id = id;
                device.device_name = name;

                device_list.emplace_back(device);
            }

            return device_list;
        });
}

std::vector<XRTCDeviceInfo> XRTCEngine::GetAudioDeviceList() {
    return XRTCGlobal::Instance()->api_thread()
        ->Invoke<std::vector<XRTCDeviceInfo>>(RTC_FROM_HERE, [=]() {
            std::vector<XRTCDeviceInfo> device_list;
            
            int16_t total = audio_device_->RecordingDevices();
            if (0 == total) {
                return device_list;
            }

            char id[128];
            char name[128];
            for (size_t index = 0; index < total; ++index) {
                id[0] = '\0';
                name[0] = '\0';

                int32_t res = audio_device_->RecordingDeviceName(
                    index, name, id);
                if (res != 0) {
                    continue;
                }

                XRTCDeviceInfo device;
                device.device_id = id;
                device.device_name = name;

                device_list.emplace_back(device);
            }

            return device_list;
        });
}

IXRTCVideoSource* XRTCEngine::CreateVideoSource(
    const XRTCVideoConfig& video_config) 
{
    return XRTCGlobal::Instance()->api_thread()->Invoke<IXRTCVideoSource*>(
        RTC_FROM_HERE, [=]() {
            return VcmCapturer::Create(video_config.width,
                video_config.height,
                video_config.fps,
                video_config.device_id);
        });
}

void XRTCEngine::DestroyVideoSource(IXRTCMediaSource* video_source) {
    XRTCGlobal::Instance()->api_thread()->PostTask(webrtc::ToQueuedTask([=]() {
        if (video_source) {
            delete video_source;
        }
    }));
}

IXRTCPreview* XRTCEngine::CreatePreview(IXRTCVideoSource* video_source, 
    const XRTCCanvas& canvas) 
{
    return XRTCGlobal::Instance()->api_thread()->Invoke<IXRTCPreview*>(
        RTC_FROM_HERE, [=]() {
            return new XRTCPreview(
                dynamic_cast<rtc::VideoSourceInterface<webrtc::VideoFrame>*>(video_source),
                canvas);
        });
}

void XRTCEngine::DestroyPreview(IXRTCPreview* preview) {
    XRTCGlobal::Instance()->api_thread()->PostTask(webrtc::ToQueuedTask([=]() {
        if (preview) {
            delete preview;
        }
    }));
}

IXRTCPusher* XRTCEngine::CreatePusher() 
{
    return XRTCGlobal::Instance()->api_thread()->Invoke<IXRTCPusher*>(
        RTC_FROM_HERE, [=]() {
            return new XRTCPusher();
        });
}

void XRTCEngine::DestroyPusher(IXRTCPusher* pusher) {
    XRTCGlobal::Instance()->api_thread()->PostTask(webrtc::ToQueuedTask([=]() {
        if (pusher) {
            delete pusher;
        }
    }));
}

IXRTCPlayer* XRTCEngine::CreatePlayer()
{
    return XRTCGlobal::Instance()->api_thread()->Invoke<IXRTCPlayer*>(
        RTC_FROM_HERE, [=]() {
            return new XRTCPlayer();
        });
}

void XRTCEngine::DestroyPlayer(IXRTCPlayer* player)
{
    XRTCGlobal::Instance()->api_thread()->PostTask(webrtc::ToQueuedTask([=]() {
        if (player) {
            delete player;
        }
    }));
}

} // namespace xrtc